package com.common.utils.BaseUtils;

import com.common.utils.BeanUtils.BeanUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;


/**
 * @author DELL
 */
public class MapUtil {

    /**
     * 将列表转换为对应的 Long类型的 map
     *
     * @param list
     * @param field
     * @param <T>
     * @return
     */
    public static <T> Map<Long, T> toMap(List<T> list, String field) {
        return toMap(list, field, Long.class);
    }

    /**
     * 将列表转换为对应的字符串 map
     *
     * @param list
     * @param field
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> toMapString(List<T> list, String field) {
        return toMap(list, field, String.class);
    }

    /**
     * 将列表转换为对应的int类型map
     *
     * @param list
     * @param field
     * @param <T>
     * @return
     */
    public static <T> Map<Integer, T> toMapInteger(List<T> list, String field) {
        return toMap(list, field, Integer.class);
    }

    private static <T, X> Map<X, T> toMap(List<T> list, String field, Class<X> clazz) {
        Map<X, T> res = new HashMap<>();
        for (T item : list) {
            if (item == null) continue;
            Class<?> itemClass = item.getClass();
            PropertyDescriptor property = null;

            try {
                property = new PropertyDescriptor(field, itemClass);
            } catch (IntrospectionException e) {
                continue;
            }

            try {
                if (property.getPropertyType().toString().equals(itemClass.toString())) {
                    continue;
                }
                Method readMethod = property.getReadMethod();
                Object invoke = readMethod.invoke(item);
                res.put((X) invoke, item);
            } catch (Exception ex) {
                continue;
            }
        }
        return res;
    }

    /**
     * @param list
     * @param field
     * @return
     * @Description 将List 分组
     * @author xhz
     * @date 2016-9-1 下午2:42:51
     * @lastModifier
     */
    public static <T, X> Map<X, List<T>> toMapList(List<T> list, String field, Class<X> clazz) {
        Map<X, List<T>> res = new HashMap<>();
        for (T item : list) {
            if (item == null) continue;
            Class<?> itemClass = item.getClass();
            PropertyDescriptor property = null;

            try {
                property = new PropertyDescriptor(field, itemClass);
            } catch (IntrospectionException e) {
                continue;
            }

            try {
                if (property.getPropertyType().toString().equals(itemClass.toString())) {
                    continue;
                }
                Method readMethod = property.getReadMethod();
                Object invoke = readMethod.invoke(item);

                if (res.containsKey((X) invoke)) {
                    List<T> tList = res.get(invoke);
                    tList.add(item);
                    res.put((X) invoke, tList);
                } else {
                    ArrayList<T> objects = new ArrayList<>();
                    objects.add(item);
                    res.put((X) invoke, objects);
                }

            } catch (Exception ex) {
                continue;
            }

        }

        return res;
    }

    public static <T> Map<Long, List<T>> toMapLongList(List<T> list, String field) {
        return toMapList(list, field, Long.class);
    }

    public static <T> Map<Integer, List<T>> toMapIntegerList(List<T> list, String field) {
        return toMapList(list, field, Integer.class);
    }

    public static <T> Map<String, List<T>> toMapStringList(List<T> list, String field) {
        return toMapList(list, field, String.class);
    }

    /**
     * 转换成对应参数
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> changeToMap(Object obj) {
        Map<String, Object> res = new HashMap<>();

        List<Field> allField = BeanUtil.getAllField(obj.getClass());

        for (Field field : allField) {

            String name = field.getName();
            if ("".equals(name) || "serialVersionUID".equals(name))
                continue;

            field.setAccessible(true);
            Object invoke = null;
            try {
                invoke = field.get(obj);

            } catch (Exception e) {
                e.printStackTrace();
            }

            Object value = invoke != null ? invoke : "";

            if ("".equals(value))
                continue;


            res.put(name, value);


        }

        return res;

    }


}
